home *** CD-ROM | disk | FTP | other *** search
-
- ;* ************************************************************************* *;
- ;* *;
- ;* I B M - P C R E A L T I M E C L O C K R O U T I N E S *;
- ;* *;
- ;* ************************************************************************* *;
-
-
- ;==========================
- ; Data Structure
- ; Definitions
- ;==========================
-
- DMTIME struc
- ;
- ttype dw 0 ; Timer type
- ; 0 = Multiple Event Interval Timer
- ; 1 = Single Event Countdown Timer
- counter dw 0 ; Tick Counter
- interval dw 0 ; Interval or Countdown Value
- event dw 0 ; Event Flag/Counter
- link dd 0 ; Link to next timer
- ;
- DMTIME ends
-
-
- ;==========================
- ; DOS Interface
- ; Definitions
- ;==========================
-
- TIMER_VECTOR equ 08H ; Interval Timer Interrupt Number
-
- DOS equ 21H ; DOS access vector
-
- DOS_SET_VECTOR equ 25H ; Set interrupt vector
- DOS_GET_VECTOR equ 35H ; Get interrupt vector
-
-
- ;==========================
- ; Timer Monitor
- ; For DM Library
- ;==========================
-
- DMIOSEG SEGMENT 'CODE'
- ASSUME cs:DMIOSEG
-
-
- ;==========================
- ; Linkage References
- ;==========================
-
- public _dmtimer_init
- public _dmtimer_release
- public _dmtimer_add
- public _dmtimer_sub
-
-
- ;==========================
- ; Local Storage
- ;==========================
-
- timer_table label word ; 1/10 of second flags
- db 0,1,0,1,0,1,0,1,0,1
- db 1,0,1,0,1,0,1,0,1,0
- db 1,1,0,1,0,1,0,1,0,1
- db 0,1,1,0,1,0,1,0,1,0
- db 1,0,1,1,0,1,0,1,0,1
- db 0,1,0,1,1,0,1,0,1,0
- db 1,0,1,0,1,1,0,1,0,1
- db 0,1,0,1,0,1,1,0,1,0
- db 1,0,1,0,1,0,1,1,0,1
- db 1
-
- oldint dw offset _dmtimer_isr ; Old interrupt vector
- dw seg _dmtimer_isr
-
- timer_tick dw 0 ; Tick counter
- root_timer label word ; Root timer
- DMTIME <0, 0, 1, 0, 0>
-
-
- ;==========================
- ; Code Section
- ;==========================
-
- _dmtimer_init proc far
- ;
- ;==========================
- ; Timer Initialization
- ;==========================
- ; Procedure: 1. Save the passed parameters
- ; 2. Init flags & pointers
- ; 3. Save old interrupt vectors
- ; 4. Set new vectors
- ; 5. Exit all done
- ; Entry: None
- ; Return: AX = -1 if error
- ; AX = 0 if init processed ok
- ;
-
- ;
- ; Access the stack frame
- ;
- push bp ; save c stack frame
- mov bp,sp
- push es ; save environment
- push ds
- push di
- push si
- mov ax,cs ; point to data
- mov ds,ax
- ;
- ; Init the clock & root timer
- ;
- mov timer_tick,0 ; current tick value
- lea si,root_timer ; point to the timer
- mov word ptr [si.ttype],0 ; type is interval timer
- mov word ptr [si.counter],0 ; counter is at 0
- mov word ptr [si.interval],1 ; interval is 1 tick
- mov word ptr [si.event],0 ; no events thus far
- mov word ptr [si.link],0 ; no other timers right now
- mov word ptr [si.link+2],0
- ;
- ; Save int vector
- ;
- mov ah,DOS_GET_VECTOR ; Save original interrupt vectors
- mov al,TIMER_VECTOR
- int DOS
- mov word ptr oldint,bx
- mov word ptr oldint+2,es
- ;
- ; Redirect ints to ISR
- ;
- push ds
- mov ax,SEG _dmtimer_isr
- mov ds,ax
- mov dx,OFFSET _dmtimer_isr
- mov ah,DOS_SET_VECTOR ; Set new interrupt vectors
- mov al,TIMER_VECTOR
- int DOS
- pop ds
- ;
- ; Exit all done
- ;
- pop si ; restore registers
- pop di
- pop ds
- pop es
- pop bp ; clear out stack frame
- ret
- ;
- _dmtimer_init endp
-
-
- _dmtimer_release proc far
- ;
- ;==========================
- ; Timer Release
- ;==========================
- ; Procedure: 1. Restore old INT vector
- ; 2. Exit all done
- ; Entry: None
- ; Return: None
- ;
- push es ; Save
- push ds
- push di
- push si
- mov ax,cs ; Access local storage
- mov ds,ax
- ;
- ; Restore int vector
- ;
- mov dx,word ptr [oldint]
- mov bx,word ptr [oldint+2]
- mov ah,DOS_SET_VECTOR ; Save original interrupt vectors
- mov al,TIMER_VECTOR
- mov ds,bx
- int DOS
- ;
- ; Exit all done
- ;
- pop si ; restore registers
- pop di
- pop ds
- pop es
- ret
- ;
- _dmtimer_release endp
-
-
- _dmtimer_add proc far
- ;
- ;==========================
- ; Timer Add
- ;==========================
- ; Procedure: 1. Setup current timer
- ; 2. Hook to end of chain
- ; 3. Exit all done
- ; Entry: [BP+6] Offset of new timer block
- ; [BP+8] Segment of new timer block
- ; Return: None
- ;
-
- ;
- ; Access the stack frame
- ;
- push bp ; save c stack frame
- mov bp,sp
- push es ; save environment
- push ds
- push di
- push si
- mov ax,cs ; point to data
- mov ds,ax
- mov di,[bp+6] ; get offset of new block
- mov dx,[bp+8] ; get segment of new block
- mov es,dx
- ;
- ; Init the new block
- ;
- mov word ptr es:[di.event],0 ; no events thus far
- mov word ptr es:[di.link],0 ; no other timers right now
- mov word ptr es:[di.link+2],0
- ;
- cmp word ptr es:[di.ttype],0 ; interval timer?
- jne dmtimer_add_20 ; countdown if not
- mov word ptr es:[di.counter],0 ; counter is at 0
- jmp dmtimer_add_40 ; now add it to the chain
- ;
- dmtimer_add_20:
- mov ax,word ptr es:[di.interval] ; counter set to equal interval
- mov word ptr es:[di.counter],ax
- ;
- ; Find the end of existing chain
- ;
- dmtimer_add_40:
- lea si,root_timer ; point to the timer
- ;
- dmtimer_add_42:
- mov ax,word ptr [si.link] ; at the null pointer?
- or ax,word ptr [si.link+2]
- jz dmtimer_add_60 ; add new to chain if so
- mov ax,word ptr [si.link+2] ; get next timer block
- mov si,word ptr [si.link]
- mov ds,ax
- jmp dmtimer_add_42 ; try again
- ;
- ; Add the new block to the chain
- ;
- dmtimer_add_60:
- cli ; freeze the world
- mov word ptr [si.link],di ; store location of new block
- mov word ptr [si.link+2],dx
- sti ; alive again
- ;
- ; Exit all done
- ;
- pop si ; restore registers
- pop di
- pop ds
- pop es
- pop bp
- ret
- ;
- _dmtimer_add endp
-
-
- _dmtimer_sub proc far
- ;
- ;==========================
- ; Timer Remove
- ;==========================
- ; Procedure: 1. Set Previous pointer to next
- ; 3. Exit all done
- ; Entry: [BP+6] Offset of old timer block
- ; [BP+8] Segment of old timer block
- ; Return: AX = 0 if no error
- ; AX = -1 if old timer block not in chain
- ;
-
- ;
- ; Access the stack frame
- ;
- push bp ; save c stack frame
- mov bp,sp
- push es ; Save
- push ds
- push di
- push si
- mov ax,cs ; Access local storage
- mov ds,ax
- mov di,[bp+6] ; get offset of old block
- mov dx,[bp+8] ; get segment of old block
- mov es,dx
- ;
- ; Find the old pointer to block
- ;
- dmtimer_sub_40:
- lea si,root_timer ; point to the timer
- ;
- dmtimer_sub_42:
- mov ax,word ptr [si.link] ; get the link offset
- cmp ax,di ; match?
- jne dmtimer_sub_44 ; next block if not
- mov ax,word ptr [si.link+2] ; get the link segment
- cmp ax,dx ; match?
- je dmtimer_sub_60 ; remove old from chain if so
- ;
- dmtimer_sub_44:
- mov ax,word ptr [si.link+2] ; get next timer block
- mov si,word ptr [si.link]
- cmp ax,si ; are we at the end?
- jne dmtimer_sub_46 ; continue if not
- or ax,ax
- jnz dmtimer_sub_46 ; continue if not
- mov ax,-1 ; else flag as block not found
- jmp dmtimer_sub_90
- ;
- dmtimer_sub_46:
- mov ds,ax ; set link segment
- jmp dmtimer_sub_42 ; try again
- ;
- ; Remove old block from the chain
- ;
- dmtimer_sub_60:
- cli ; freeze the world
- mov ax,word ptr es:[di.link] ; squeeze out the link
- mov word ptr [si.link],ax
- mov ax,word ptr es:[di.link+2]
- mov word ptr [si.link+2],ax
- sti ; alive again
- xor ax,ax ; no errors
- ;
- ; Exit all done
- ;
- dmtimer_sub_90:
- pop si ; restore registers
- pop di
- pop ds
- pop es
- pop bp
- ret
- ;
- _dmtimer_sub endp
-
-
- _dmtimer_isr proc far
- ;
- ;==========================
- ; Timer ISR
- ;==========================
- ; Procedure: 1. Test if active tick
- ; 2. Goto 17 if not
- ; 3. Get next block
- ; 4. Goto 17 if done
- ; 5. Test if interval
- ; 6. Goto 12 if not
- ; 7. Increment counter
- ; 8. If interval not reached goto 3
- ; 9. Reset counter
- ; 10. Increment event count
- ; 11. Goto xx
- ; 12. If event already tripped then goto 3
- ; 13. Countdown a tick
- ; 14. If not 0 then goto 3
- ; 15. Reset counter
- ; 16. Set event flag
- ; 17. Bump tick count
- ; 18. If tick count != 39 then goto 20
- ; 19. Reset tick count
- ; 20. Pass on to regular clock ISR
- ; Entry: None
- ; Return: None
- ;
- push es ; Save
- push ds
- push di
- push si
- push bx
- push ax
- mov ax,cs ; Access local storage
- mov ds,ax
- ;
- ; Restore int vector
- ;
- lea bx,timer_table ; point to flag table
- add bx,timer_tick ; add in current tick count (index)
- cmp word ptr [bx],0 ; test if this is a 1/10 sec tick
- jnz dmtimer_isr_10 ; process if so
- jmp dmtimer_isr_90 ; else exit
- ;
- ; Get the first timer block
- ;
- dmtimer_isr_10:
- ;
- mov ax,cs ; point to 1st block
- mov es,ax
- lea di,root_timer
- jmp dmtimer_isr_14
- ;
- ; Get next timer block
- ;
- dmtimer_isr_12:
- mov ax,word ptr es:[di.link+2] ; get next block
- mov di,word ptr es:[di.link]
- mov es,ax
- ;
- ; Exit if null block
- ;
- dmtimer_isr_14:
- mov ax,es ; test if null block
- or ax,di
- jnz dmtimer_isr_16 ; dispatch if not
- jmp dmtimer_isr_90 ; else exit
- ;
- dmtimer_isr_16:
- cmp word ptr es:[di.ttype],0 ; is it an interval timer?
- je dmtimer_isr_20 ; process if so
- jmp dmtimer_isr_40 ; else assume countdown
- ;
- ; Process interval timer
- ;
- dmtimer_isr_20:
- inc word ptr es:[di.counter] ; bump the counter
- mov ax,word ptr es:[di.counter] ; test if interval reached
- cmp ax,word ptr es:[di.interval]
- jnz dmtimer_isr_12 ; next timer block if not
- mov word ptr es:[di.counter],0 ; reset the counter
- inc word ptr es:[di.event] ; bump the event counter
- jmp dmtimer_isr_12 ; next timer block
- ;
- ; Process countdown timer
- ;
- dmtimer_isr_40:
- cmp word ptr es:[di.event],0 ; test if event already flagged
- jne dmtimer_isr_12 ; next timer block if not
- dec word ptr es:[di.counter] ; bump the counter
- jnz dmtimer_isr_12 ; next timer block if not expired
- mov ax,word ptr es:[di.interval] ; reset the counter
- mov word ptr es:[di.counter],ax ; reset the counter
- inc word ptr es:[di.event] ; bump the event counter
- jmp dmtimer_isr_12 ; next timer block
- ;
- ; Bump counter and adjust if needed
- ;
- dmtimer_isr_90:
- inc timer_tick ; bump timer tick counter
- cmp timer_tick,91 ; at end?
- jne dmtimer_isr_92 ; skip if not
- mov timer_tick,0 ; else reset
- ;
- ; Exit all done
- ;
- dmtimer_isr_92:
- pop ax ; restore registers
- pop bx
- pop si
- pop di
- pop ds
- pop es
- jmp dword ptr cs:oldint ; pass on to regualr clock routine
- ;
- _dmtimer_isr endp
-
-
- DMIOSEG ends
- END
-